package kv

import (
	"bufio"
	"os"
	"strings"
)

type KV struct {
	dict     map[string]*string
	filename string
}

func NewKV() *KV {
	kv := new(KV)
	kv.dict = map[string]*string{}
	return kv
}

func (m *KV) Open(filename string) (kv *KV) {
	f, err := os.Open(filename)
	if err != nil {
		return nil
	}
	defer f.Close()
	buf := bufio.NewReader(f)
	kv = new(KV)
	kv.dict = map[string]*string{}
	kv.filename = filename
	for line, err := buf.ReadString('\n'); err == nil || len(line) > 0; line, err = buf.ReadString('\n') {
		ss := strings.SplitN(line, ",", 2)
		for i := range ss {
			ss[i] = strings.TrimSpace(ss[i])
		}
	}

	return
}

func (m *KV) Get(key string) string {
	v := m.dict[key]
	if v != nil {
		return *v
	}
	return ""
}

func (m *KV) Delete(key string) (err error) {
	delete(m.dict, key)
	return m.Save()
}

func (m *KV) Insert(key, value string) (err error) {
	m.dict[key] = &value
	return m.Save()
}

func (m *KV) Save() (err error) {
	f, err := os.Create(m.filename + ".tmp")
	if err != nil {
		return
	}
	buf := bufio.NewWriter(f)
	for k, v := range m.dict {
		buf.WriteString(k)
		buf.WriteByte(',')
		buf.WriteString(*v)
		buf.WriteByte('\n')
	}
	f.Close()
	os.Rename(m.filename, m.filename+".tmp")
	return
}

func (m *KV) DeleteNotIn(keys []string) (err error) {
	dict := map[string]*string{}
	for _, key := range keys {
		dict[key] = nil
	}
	for k, v := range m.dict {
		if _, ok := dict[k]; ok {
			dict[k] = v
		}
	}
	m.dict = dict
	return m.Save()
}
